#include "NormalMappingForwardFX.h"

NormalMappingForwardFX::NormalMappingForwardFX(ID3D11Device* device)
	: AbstractFX(device, L"FX/NormalMappingForward.fxo")
{
	InitInputLayout(device);
	InitShaderVariablePointers();
}

NormalMappingForwardFX::~NormalMappingForwardFX()
{}

void NormalMappingForwardFX::InitInputLayout(ID3D11Device* device)
{
	const D3D11_INPUT_ELEMENT_DESC inputLayout[] = 
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,       0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"TANGENT",  0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	CreateInputLayout(device, inputLayout, 4);
}

void NormalMappingForwardFX::InitShaderVariablePointers()
{
	worldVar         = effect->GetVariableByName("world")->AsMatrix();
	worldInvTransVar = effect->GetVariableByName("worldInvTrans")->AsMatrix();
	worldViewProjVar = effect->GetVariableByName("worldViewProj")->AsMatrix();
	texTransformVar  = effect->GetVariableByName("texTransform")->AsMatrix();

	diffuseMapVar = effect->GetVariableByName("diffuseMap")->AsShaderResource();
	normalMapVar  = effect->GetVariableByName("normalMap")->AsShaderResource();

	materialVar = effect->GetVariableByName("mat");
	eyePosVar   = effect->GetVariableByName("eyePosW")->AsVector();

	direcLightVar = effect->GetVariableByName("dLights");
	pointLightVar = effect->GetVariableByName("pLights");
	spotLightVar  = effect->GetVariableByName("sLights");
}

void NormalMappingForwardFX::SetCBufferPerObject(CXMMATRIX& world, 
		CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, 
		CXMMATRIX& texTrans, Material& mat)
{
	worldVar->SetMatrix(reinterpret_cast<const float*>(&world));
	worldInvTransVar->SetMatrix(reinterpret_cast<const float*>(&worldInvTrans));
	worldViewProjVar->SetMatrix(reinterpret_cast<const float*>(&worldViewProj));
	texTransformVar->SetMatrix(reinterpret_cast<const float*>(&texTrans));

	materialVar->SetRawValue(&mat, 0, sizeof(Material));
}

void NormalMappingForwardFX::SetShaderResources(ID3D11ShaderResourceView* diffuseMap,
	ID3D11ShaderResourceView* normalMap)
{
	diffuseMapVar->SetResource(diffuseMap);
	normalMapVar->SetResource(normalMap);
}

void NormalMappingForwardFX::SetCBufferLighting(XMFLOAT3& eye, bool updateLights,
	DirectionalLight* dLights, unsigned dLightCount,
	PointLight* pLights, unsigned pLightCount, 
	SpotLight* sLights, unsigned sLightCount)
{
	eyePosVar->SetRawValue(&eye, 0, sizeof(XMFLOAT3));
	
	if (updateLights)
	{
		//Clamp dLightCount to  <= 3
		if (dLightCount > 3)
			dLightCount = 3;

		direcLightVar->SetRawValue(dLights, 0, sizeof(DirectionalLight) * dLightCount);

		//Clamp point light count to <=100
		if (pLightCount > 100)
			pLightCount = 100;

		pointLightVar->SetRawValue(pLights, 0, sizeof(PointLight) * pLightCount);

		//Clamp number of point lights to <=100
		if (sLightCount > 100)
			sLightCount = 100;

		spotLightVar->SetRawValue(sLights, 0, sizeof(SpotLight) * sLightCount);
	}
}